package com.lcpay.download.core;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.lcpay.download.utils.FuncUtils;

/**
 * 类AbstractDownExecute.java的实现描述：操作核心类
 * 
 * @author chenrs 2015年12月7日 下午11:24:23
 */
public abstract class AbstractDownExecute extends AbstractHttpConnection {

    private static Logger       logger = LoggerFactory.getLogger(AbstractDownExecute.class);
    // 保存文件
    protected String            saveurl;
    // 保存文件
    private File                writeFile;
    // 监控文件
    private File                monitorFile;
    // 监控文件后缀名
    private static final String LOCKED = ".locked";
    // 文件跳过的长度
    private long                seek   = 0;

    public AbstractDownExecute(String saveurl, String url) {
        super(url);
        this.saveurl = saveurl;

    }

    // 创建文件
    protected boolean createFile() {
        writeFile = new File(saveurl);
        try {

            if (writeFile.getParentFile().isDirectory() && !writeFile.getParentFile().exists()) {
                writeFile.getParentFile().mkdirs();
            }

            boolean writefileExists = writeFile.isFile();
            if (!writefileExists) {
                writeFile.createNewFile();
            }

            monitorFile = new File(saveurl + LOCKED);

            if (!monitorFile.isFile()) {
                // 不存在创建
                monitorFile.createNewFile();
            } else {
                // 存在监控文件且原来文件也存在 解析监控文件内容
                if (writefileExists) {
                    resolveMonitorinfo();
                }

            }

        } catch (IOException e) {
            logger.error("创建文件失败", e);
            return false;
        }
        return true;
    }

    /**
     * 解析监控文件内容
     * 
     * @throws IOException
     */
    private void resolveMonitorinfo() throws IOException {

        RandomAccessFile inputstream = new RandomAccessFile(monitorFile, "rw");
        byte[] cache = new byte[1024 * 32];
        int n = 0;
        StringBuilder info = new StringBuilder();
        while ((n = inputstream.read(cache, 0, cache.length)) != -1) {
            info.append(new String(cache, 0, n));
        }
        inputstream.close();

        if (!FuncUtils.isNull(info.toString())) {

            JSONObject result = JSON.parseObject(info.toString());

            int compelete = result.getIntValue("compelete");

            if (compelete > writeFile.length() || getContentLength() != result.getIntValue("total")) {
                logger.error("完成字节数大于已下载文件大小||文件大小发生变化 重新下载");
                writeFile.delete();
                writeFile.createNewFile();
                return;
            }
            // 设置跳过的值
            seek = compelete;

        }
    }

    /**
     * 下载
     * 
     * @throws IOException
     */
    protected void startDwonload() throws IOException {

        HttpURLConnection urlConnection = getUrlConnection();

        if (checkSupportBreakPointContinue()) {
            urlConnection = getNewConnection();
            StringBuilder range = new StringBuilder();
            range.append("bytes=");
            range.append(seek);
            range.append("-");
            urlConnection.setRequestProperty("Range", range.toString());
        }
        InputStream inputstream = urlConnection.getInputStream();

        if (checkSupportMonitor()) {
            // 开始监控
            super.start();
        }

        byte[] cache = new byte[1024 * 32];
        int n = 0;

        RandomAccessFile randomAccessFile = new RandomAccessFile(writeFile, "rw");

        if (checkSupportBreakPointContinue()) {
            randomAccessFile.seek(seek);
        }

        while ((n = inputstream.read(cache, 0, cache.length)) != -1) {
            randomAccessFile.write(cache, 0, n);
        }

        randomAccessFile.close();
        urlConnection.disconnect();

    }

    /**
     * 下载完成回调事件
     */
    protected void finishDownload() {
        if (writeFile.length() == getContentLength()) {
            // 删除监控文件
            monitorFile.delete();
            // 关闭监控
            stop();
            // 关闭http连接
            closeHttpConnection();

        }
    }

    /**
     * 定时写监控文件内容
     */
    protected void writeMonitorFile() throws IOException {
        RandomAccessFile randomAccessFile = new RandomAccessFile(monitorFile, "rw");
        JSONObject monitinfo = new JSONObject();
        monitinfo.put("date", new SimpleDateFormat("yyyyMMdd HH:mm:ss").format(new Date()));
        monitinfo.put("compelete", String.valueOf(writeFile.length()));
        monitinfo.put("total", getContentLength());
        logger.info(monitinfo.toJSONString());
        randomAccessFile.write(monitinfo.toJSONString().getBytes());
        randomAccessFile.close();
    }

    private boolean checkSupportMonitor() {
        return getContentLength() != -1;
    }

    private boolean checkSupportBreakPointContinue() {
        return seek != 0;
    }
}
